package com.fx.usercenter.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fx.usercenter.common.BaseResponse;
import com.fx.usercenter.common.ErrorCode;
import com.fx.usercenter.common.ResultUtils;
import com.fx.usercenter.exception.BusinessException;
import com.fx.usercenter.model.domain.User;
import com.fx.usercenter.mapper.UserMapper;
import com.fx.usercenter.model.dto.LoginRequest;
import com.fx.usercenter.model.dto.RegisterRequest;
import com.fx.usercenter.service.UserService;
import com.fx.usercenter.utlils.CookieUtil;
import com.fx.usercenter.utlils.JsonUtil;
import com.fx.usercenter.utlils.RedisUtil;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.prefs.BackingStoreException;
import static com.fx.usercenter.contant.UserConstant.ADMIN_ROLE;
import static com.fx.usercenter.contant.UserConstant.USER_LOGIN_STATE;


@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
    @Resource
    UserMapper userMapper;
    @Resource
    UserService userService;

    @Resource
    private RedisTemplate redisTemplate;

    /*@Autowired
    private RedisUtil redisUtil;*/

    /**
     * 注册
     * @param registerRequest
     * @return
     */
    @PostMapping("/register")
    public BaseResponse<Long> register(@RequestBody RegisterRequest registerRequest){
     //注册需要账号,密码,星球编号
        long result = userService.Register(registerRequest.getUserAccount(), registerRequest.getUserPassword(), registerRequest.getPlanetCode());
        return ResultUtils.success(result);
    }

    /***
     * 登录
     * @param loginRequest
     * @param request
     * @return
     */
    @PostMapping("/login")
    public BaseResponse<User> login(@RequestBody LoginRequest loginRequest, HttpServletRequest request, HttpServletResponse response) throws JsonProcessingException {
        ValueOperations ops = redisTemplate.opsForValue();
        String s = request.getSession().getId();
        if (redisTemplate.hasKey(s)) {
            //登录过重复
            throw new BusinessException(ErrorCode.CT_LOGIN);
        } else {
            //未登录,登录存入redis
            User loginUser = userService.Login(loginRequest.getUserAccount(), loginRequest.getUserPassword(), request);
            ObjectMapper om = new ObjectMapper();
            Gson gson = new Gson();
            ops.set(s, om.writeValueAsString(gson.toJson(loginUser)));//将凭证存入Redis
            redisTemplate.expire(s, 30, TimeUnit.MINUTES);//设置过期时间，30分钟
            return ResultUtils.success(loginUser);
        }

    }
    /**
     * 1、读取cookie  （测试）
     * 2、将cookie的值当做redis的key将对象取出，再反序列化就可以啦
     * @param request
     * @return
     */
  /*  @GetMapping(value = "get_user_info")
    public BaseResponse<User> getUserInfo(HttpServletRequest request){
        //读取sessionID
        //String sessionID = CookieUtil.readLoginToken(request);
        String sessionID = request.getSession().getId();
        if(StringUtils.isBlank(sessionID)){
           throw new BusinessException(ErrorCode.NOT_LOGIN,"未登录");
        }
        //从Redis中获取用户的数据
        User user = (User) redisUtil.get(sessionID);
        if(user != null){
            return ResultUtils.success(user);
        }
        throw new BusinessException(ErrorCode.NOT_LOGIN,"未登录");
    }*/
    /**
     * 删除
     * @param id
     * @return
     */
    @PostMapping("/delete")
    public BaseResponse<Long> delete(@RequestParam int id){
        //登录需要账号,密码
        long result = userService.deleteById(id);
        return ResultUtils.success(result);
    }

    /**
     * 新增用户
     * @param user
     * @return
     */
    @PostMapping("/add")
    public BaseResponse<Long> add(@RequestBody User user){
        long result = userService.addUser(user);
        return ResultUtils.success(result);
    }

    /**
     * 修改用户
     * @param user
     * @param request
     * @return
     */
    @PostMapping("/update")
    public BaseResponse<Long> update(@RequestBody User user,HttpServletRequest request){
        long result = userService.updateUser(user, request);
        return ResultUtils.success(result);
    }

    /**
     * 更改用户权限（管理员）
     * @param userAccount
     * @param userRole
     * @param request
     * @return
     */
    @PostMapping("/updateRole")
    public BaseResponse<Long> updateRole(@RequestParam  String userAccount ,@RequestParam(required = true,defaultValue = "0") int userRole ,HttpServletRequest request){
       if(!isAdmin(request)){
           throw new BusinessException(ErrorCode.NO_AUTH);
       }
        long result = userService.updateRole(userAccount, userRole, request);
        return ResultUtils.success(result);
    }
    /**
     * 获取当前用户
     * @param request
     * @return
     */
    @GetMapping("/current")
    public BaseResponse<User> currentUser(HttpServletRequest request){
      if(request == null){
         throw new BusinessException(ErrorCode.PARAMS_ERROR);
      }
      
     Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
     User user = (User) userObj;
     if (user == null){
        throw new BusinessException(ErrorCode.PARAMS_ERROR);
     }
     return ResultUtils.success(user);
    }

    /**
     * 退出登录
     * @param request
     * @return
     */
    @GetMapping("/logout")
    public BaseResponse<Long> longOut(HttpServletRequest request){
        if(request == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
        User user = (User) userObj;
        if (user == null){
            throw new BusinessException(ErrorCode.NOT_LOGIN,"没有登录");
        }
        long result = userService.loginOut(request);
        return ResultUtils.success(result);
    }
    /**
     * 查询所有
     * @return
     */
    @GetMapping ( "/list")
    public BaseResponse<List<User>> findUsers(HttpServletRequest request){
        if (!isAdmin(request)){
          return ResultUtils.error(ErrorCode.NO_AUTH);
        }
        //测试  redis 缓存
        String redisKey = String.format("fx:user:list:%s",request.getSession().getId());
        ValueOperations valueOperations = redisTemplate.opsForValue();
        //如果有缓存，直接读取
        List usersList = (List) valueOperations.get(redisKey);
        if(usersList != null){
            return ResultUtils.success(usersList);
        }
        //无缓存，查数据库
          usersList = userService.findUsers();
        //写缓存,10s过期
        try {
            valueOperations.set(redisKey,usersList,30000, TimeUnit.MILLISECONDS);
        } catch (Exception e){
            log.error("redis set key error",e);
        }
          return ResultUtils.success(usersList);

    }

    /**
     * 更多条件查用户(给管理员用的)...测试
     * @param userName
     * @param gender
     * @return
     */
    @GetMapping("/finder")
    public  BaseResponse<List<User>>findUser(String userName,int gender,HttpServletRequest request){
        if (!isAdmin(request)){
            throw new BusinessException(ErrorCode.NO_AUTH);
        }
      //按名字查询
      if (userName != null && gender == 3){
          List users = userService.findUsers(userName, 3, request);
          return ResultUtils.success(users);
      }
      //按性别查询
        if (userName == null && gender != 3){
          List users = userService.findUsers(null, gender, request);
            return ResultUtils.success(users);
        }
        //按两个查询
        if (userName != null && gender != 3){
            List users = userService.findUsers(userName, gender, request);
            return ResultUtils.success(users);

        }
        List users = userService.findUsers();
        return ResultUtils.success(users);
    }

    /**
     * 分页查询
     * @return
     */
    @GetMapping("/limitList")
    public BaseResponse<Page<User>> findUser(HttpServletRequest request){
        if (!isAdmin(request)){
            throw new BusinessException(ErrorCode.NO_AUTH);
        }
        Page<User> pageList = userService.limitSelectUsers();
        return ResultUtils.success(pageList);
    }

    /**
     * 分页查询名称（测试）
     * @return
     */
    @GetMapping("/nameList")
    public Page<User> findUserName(HttpServletRequest request) {
        Page<User> pageList = userMapper.selectPageVo(new Page<>(1,3));
        return pageList;
    }
    /**
     * 测试拦截是否生效 （测试）
     */
    @GetMapping("/test")
    public String test( ) {
        System.out.println("放行成功");
        return "放行成功";
    }
    /**
     * 文件（图片上传） （测试）
     * @param file
     * @return
     */
    @PostMapping("/upload")
    public String upload(MultipartFile file) {
        if (file.isEmpty()) {
            return "图片为空";
        }
        // 获取原始文件名和扩展名
        String originalFilename = file.getOriginalFilename();
        String fileNamePrefix = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
        String fileNameSuffix = "." + originalFilename.split("\\.")[1];
        // 生成新的文件名
        String fileName = fileNamePrefix + fileNameSuffix;
        // 获取项目根目录的绝对路径
        ApplicationHome applicationHome = new ApplicationHome(this.getClass());
        String pre = applicationHome.getDir().getParentFile().getParentFile().getAbsolutePath() +
                "/src/main/resources/static/images/";
        String path = pre + fileName;
        try {
            // 将上传的文件保存到本地
            file.transferTo(new File(path));
            // 返回文件的本地路径
            return path;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "图片上传失败";
    }
    /**
     * 对用户鉴权
     * @param request
     * @return
     */
    public Boolean isAdmin(HttpServletRequest request){
        //根据登录态拿到信息
        Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
        //将 userObj 强转user
        User user =(User) userObj;
        if(user == null || user.getUserRole() != ADMIN_ROLE){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        return true;
    }

}
